package com.wyix.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wyix.common.BusinessException;
import com.wyix.common.PageResult;
import com.wyix.domain.dto.ScoreDTO;
import com.wyix.domain.dto.ScoreQueryDTO;
import com.wyix.domain.entity.ScoreDO;
import com.wyix.mapper.CourseMapper;
import com.wyix.mapper.ScoreMapper;
import com.wyix.mapper.StudentMapper;
import com.wyix.service.ScoreService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 成绩服务实现类
 */
@Slf4j
@Service
public class ScoreServiceImpl implements ScoreService {

    @Resource
    private ScoreMapper scoreMapper;

    @Resource
    private StudentMapper studentMapper;

    @Resource
    private CourseMapper courseMapper;

    /**
     * 新增成绩
     */
    @Override
    @Transactional
    public void addScore(ScoreDTO scoreDTO) {
        log.info("新增成绩: {}", scoreDTO);

        // 检查学生是否存在
        if (studentMapper.selectById(scoreDTO.getStudentId()) == null) {
            log.warn("新增成绩失败，学生不存在，ID: {}", scoreDTO.getStudentId());
            throw new BusinessException("学生不存在");
        }

        // 检查课程是否存在
        if (courseMapper.selectById(scoreDTO.getCourseId()) == null) {
            log.warn("新增成绩失败，课程不存在，ID: {}", scoreDTO.getCourseId());
            throw new BusinessException("课程不存在");
        }

        // 检查该学生该课程是否已存在成绩
        ScoreDO existingScore = scoreMapper.selectByStudentAndCourse(
                scoreDTO.getStudentId(), scoreDTO.getCourseId());
        if (existingScore != null) {
            log.warn("新增成绩失败，该学生该课程已存在成绩，学生ID: {}, 课程ID: {}",
                    scoreDTO.getStudentId(), scoreDTO.getCourseId());
            throw new BusinessException("该学生该课程已存在成绩");
        }

        // 转换DTO为实体
        ScoreDO score = new ScoreDO();
        BeanUtils.copyProperties(scoreDTO, score);

        // 执行新增
        int rows = scoreMapper.insert(score);
        if (rows != 1) {
            log.error("新增成绩失败: {}", scoreDTO);
            throw new BusinessException("新增成绩失败");
        }

        log.info("新增成绩成功，ID: {}", score.getId());
    }

    /**
     * 根据ID删除成绩
     */
    @Override
    @Transactional
    public void deleteScore(Long id) {
        log.info("删除成绩，ID: {}", id);

        // 检查成绩是否存在
        ScoreDO score = scoreMapper.selectById(id);
        if (score == null) {
            log.warn("删除成绩失败，成绩不存在，ID: {}", id);
            throw new BusinessException("成绩不存在");
        }

        // 执行删除
        int rows = scoreMapper.deleteById(id);
        if (rows != 1) {
            log.error("删除成绩失败，ID: {}", id);
            throw new BusinessException("删除成绩失败");
        }

        log.info("删除成绩成功，ID: {}", id);
    }

    /**
     * 更新成绩信息
     */
    @Override
    @Transactional
    public void updateScore(ScoreDTO scoreDTO) {
        log.info("更新成绩: {}", scoreDTO);

        // 检查ID是否存在
        if (scoreDTO.getId() == null) {
            log.warn("更新成绩失败，ID不能为空");
            throw new BusinessException("ID不能为空");
        }

        // 检查成绩是否存在
        ScoreDO existingScore = scoreMapper.selectById(scoreDTO.getId());
        if (existingScore == null) {
            log.warn("更新成绩失败，成绩不存在，ID: {}", scoreDTO.getId());
            throw new BusinessException("成绩不存在");
        }

        // 如果学生ID或课程ID有变化，需要检查
        if (!existingScore.getStudentId().equals(scoreDTO.getStudentId()) ||
                !existingScore.getCourseId().equals(scoreDTO.getCourseId())) {

            // 检查新的学生是否存在
            if (studentMapper.selectById(scoreDTO.getStudentId()) == null) {
                log.warn("更新成绩失败，学生不存在，ID: {}", scoreDTO.getStudentId());
                throw new BusinessException("学生不存在");
            }

            // 检查新的课程是否存在
            if (courseMapper.selectById(scoreDTO.getCourseId()) == null) {
                log.warn("更新成绩失败，课程不存在，ID: {}", scoreDTO.getCourseId());
                throw new BusinessException("课程不存在");
            }

            // 检查新的学生-课程组合是否已存在成绩
            ScoreDO scoreByStuAndCourse = scoreMapper.selectByStudentAndCourse(
                    scoreDTO.getStudentId(), scoreDTO.getCourseId());
            if (scoreByStuAndCourse != null && !scoreByStuAndCourse.getId().equals(scoreDTO.getId())) {
                log.warn("更新成绩失败，该学生该课程已存在成绩，学生ID: {}, 课程ID: {}",
                        scoreDTO.getStudentId(), scoreDTO.getCourseId());
                throw new BusinessException("该学生该课程已存在成绩");
            }
        }

        // 转换DTO为实体
        ScoreDO score = new ScoreDO();
        BeanUtils.copyProperties(scoreDTO, score);

        // 执行更新
        int rows = scoreMapper.updateById(score);
        if (rows != 1) {
            log.error("更新成绩失败: {}", scoreDTO);
            throw new BusinessException("更新成绩失败");
        }

        log.info("更新成绩成功，ID: {}", scoreDTO.getId());
    }

    /**
     * 根据ID查询成绩
     */
    @Override
    public ScoreDO getScoreById(Long id) {
        log.info("查询成绩，ID: {}", id);

        if (id == null) {
            log.warn("查询成绩失败，ID不能为空");
            throw new BusinessException("ID不能为空");
        }

        ScoreDO score = scoreMapper.selectById(id);
        if (score == null) {
            log.warn("查询成绩失败，成绩不存在，ID: {}", id);
            throw new BusinessException("成绩不存在");
        }

        log.info("查询成绩成功，ID: {}", id);
        return score;
    }

    /**
     * 多条件分页查询成绩
     */
    @Override
    public PageResult<ScoreDO> queryScores(ScoreQueryDTO queryDTO) {
        log.info("查询成绩列表，条件: {}", queryDTO);

        // 分页查询
        PageHelper.startPage(queryDTO.getPageNum(), queryDTO.getPageSize());
        Page<ScoreDO> page = (Page<ScoreDO>) scoreMapper.selectByCondition(queryDTO);

        // 封装分页结果
        PageResult<ScoreDO> pageResult = new PageResult<>(
                page.getTotal(),
                page.getPages(),
                page.getPageNum(),
                page.getPageSize(),
                page.getResult()
        );

        log.info("查询成绩列表成功，总记录数: {}", page.getTotal());
        return pageResult;
    }

    /**
     * 根据学生ID查询成绩
     */
    @Override
    public List<ScoreDO> getScoresByStudentId(Long studentId) {
        log.info("根据学生ID查询成绩，学生ID: {}", studentId);

        if (studentId == null) {
            log.warn("根据学生ID查询成绩失败，学生ID不能为空");
            throw new BusinessException("学生ID不能为空");
        }

        // 检查学生是否存在
        if (studentMapper.selectById(studentId) == null) {
            log.warn("根据学生ID查询成绩失败，学生不存在，ID: {}", studentId);
            throw new BusinessException("学生不存在");
        }

        List<ScoreDO> scores = scoreMapper.selectByStudentId(studentId);
        log.info("根据学生ID查询成绩成功，学生ID: {}, 成绩数量: {}", studentId, scores.size());
        return scores;
    }

    /**
     * 根据课程ID查询成绩
     */
    @Override
    public List<ScoreDO> getScoresByCourseId(Long courseId) {
        log.info("根据课程ID查询成绩，课程ID: {}", courseId);

        if (courseId == null) {
            log.warn("根据课程ID查询成绩失败，课程ID不能为空");
            throw new BusinessException("课程ID不能为空");
        }

        // 检查课程是否存在
        if (courseMapper.selectById(courseId) == null) {
            log.warn("根据课程ID查询成绩失败，课程不存在，ID: {}", courseId);
            throw new BusinessException("课程不存在");
        }

        List<ScoreDO> scores = scoreMapper.selectByCourseId(courseId);
        log.info("根据课程ID查询成绩成功，课程ID: {}, 成绩数量: {}", courseId, scores.size());
        return scores;
    }
}